package com.panda.autotest.service;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.commons.CommonsMultipartFile;

import com.panda.autotest.controller.CaseSearchCriteria;
import com.panda.autotest.core.AutoTestConstants;
import com.panda.autotest.core.SpringContextUtil;
import com.panda.autotest.core.parse.CaseConfig;
import com.panda.autotest.core.parse.CaseConfigManager;
import com.panda.autotest.dao.CaseDao;
import com.panda.autotest.dao.model.Case;
import com.panda.autotest.dao.model.CaseExample;
import com.panda.autotest.dao.model.CaseExample.Criteria;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;

@Service
public class CaseServiceImpl implements CaseService {
	private Logger logger = LoggerFactory.getLogger(CaseServiceImpl.class);
	@Autowired
	private CaseConfigManager caseConfigManager;
	@Autowired
	private CaseDao caseDao;

	@Override
	public CaseSearchCriteria getCaseList(CaseSearchCriteria searchCriteria) {
		CaseExample caseExample = new CaseExample();
		caseExample.setOrderBy(searchCriteria.getOrderBy());
		caseExample.setOrderByClause(searchCriteria.getOrderByClause());
		String fileName = searchCriteria.getFileName();
		Criteria criteria = caseExample.createCriteria();
		if (StringUtils.hasText(fileName)) {
			criteria.andFileNameLike("%" + fileName + "%");
		}
		String name = searchCriteria.getName();
		if (StringUtils.hasText(name)) {
			criteria.andCaseNameLike("%" + name + "%");
		}
		String siteCode = searchCriteria.getSiteCode();
		if (StringUtils.hasText(siteCode)) {
			criteria.andLoginCompanyCodeLike("%" + siteCode + "%");
		}
		String status = searchCriteria.getStatus();
		if (StringUtils.hasText(status)) {
			criteria.andStatusLike("%" + status + "%");
		}
		PageHelper.startPage(searchCriteria.getPage(), searchCriteria.getLimit());
		List<Case> caseList = caseDao.selectByExample(caseExample);
		PageInfo<Case> pageInfo = new PageInfo<Case>(caseList);
		searchCriteria.setCount(pageInfo.getTotal());
		searchCriteria.setCaseList(caseList);
		return searchCriteria;
	}

	@Transactional
	@Override
	public void createCase(CommonsMultipartFile file) {
		try {
			String fileName = file.getFileItem().getName();
			String location = caseConfigManager.getLocation();
			Resource[] resources = SpringContextUtil.getResources(location);
			String path = null;
			int index = 0;
			if (resources == null || resources.length <= 0) {
				index = location.lastIndexOf("/");
				if (index == -1) {
					index = location.lastIndexOf("\\");
				}
				if (index != -1) {
					path = location.substring(0, index);
				}
				resources = SpringContextUtil.getResources(path);
			}
			path = resources[0].getFile().getAbsolutePath();
			index = path.lastIndexOf(File.separator);
			if (index != -1 && path.contains(".")) {
				path = path.substring(0, index);
			}
			index = fileName.lastIndexOf(".");
			if (index != -1) {
				fileName = fileName.substring(0, index) + "_" + System.currentTimeMillis() + fileName.substring(index);
			}
			path = path + File.separator + fileName;
			CaseConfig caseConfig = caseConfigManager.buildCaseConfig(file.getInputStream(), fileName, path, null);
			caseDao.insert((Case) caseConfig);
			caseConfigManager.updateCache(caseConfig);
			IOUtils.copy(file.getInputStream(), new FileOutputStream(path));
		} catch (Exception e) {
			logger.error("error", e);
			throw new RuntimeException(e);
		}
	}

	@Transactional
	@Override
	public void deleteCases(List<String> keys) {
		for (String key : keys) {
			CaseConfig caseConfig = caseConfigManager.getCaseConfigMap().get(key);
			if (caseConfig == null) {
				throw new RuntimeException("案例已经被删除或更新");
			}
			if (AutoTestConstants.RUN.equals(caseConfig.getStatus())
					|| AutoTestConstants.WAIT_RUN.equals(caseConfig.getStatus())) {
				throw new RuntimeException("案例正在运行中,或者等待运行");
			}
			caseDao.deleteByPrimaryKey(key);
		}
		caseConfigManager.clearCaches(keys);
	}

	@Transactional
	@Override
	public void refreshCases(List<String> keys) {
		List<CaseConfig> caseConfigs = new ArrayList<CaseConfig>();
		try {
			for (String key : keys) {
				CaseConfig caseConfig = caseConfigManager.getCaseConfigMap().get(key);
				if (caseConfig == null) {
					throw new RuntimeException("案例已经被删除或更新");
				}
				if (AutoTestConstants.RUN.equals(caseConfig.getStatus())
						|| AutoTestConstants.WAIT_RUN.equals(caseConfig.getStatus())) {
					throw new RuntimeException("案例正在运行中,或者等待运行");
				}
				caseConfig = caseConfigManager.buildCaseConfig(new FileInputStream(new File(caseConfig.getFilePath())),
						caseConfig.getFileName(), caseConfig.getFilePath(), key);

				caseDao.updateByPrimaryKeySelective((Case) caseConfig);
				caseConfigs.add(caseConfig);
			}
			caseConfigManager.updateCaches(caseConfigs);
		} catch (Exception e) {
			logger.error("error", e);
			throw new RuntimeException(e);
		}
	}

	@Transactional
	@Override
	public void updateCase(Map<String, String> dataMap) {
		try {
			String uuid = dataMap.get("uuid");
			String xml = dataMap.get("xml");
			CaseConfig caseConfig = caseConfigManager.getCaseConfigMap().get(uuid);
			if (caseConfig == null) {
				throw new RuntimeException("案例已经被删除或更新");
			}
			if (AutoTestConstants.RUN.equals(caseConfig.getStatus())
					|| AutoTestConstants.WAIT_RUN.equals(caseConfig.getStatus())) {
				throw new RuntimeException("案例正在运行中,或者等待运行");
			}
			caseConfig = caseConfigManager.buildCaseConfig(new ByteArrayInputStream(xml.getBytes("UTF-8")),
					caseConfig.getFileName(), caseConfig.getFilePath(), uuid);
			Case dbCase = caseDao.selectByPrimaryKey(uuid);
			caseConfigManager.updateCacheFromDb(dbCase, caseConfig);
			caseDao.updateByPrimaryKeySelective((Case) caseConfig);
			IOUtils.copy(new ByteArrayInputStream(xml.getBytes("UTF-8")),
					new FileOutputStream(caseConfig.getFilePath()));
			caseConfigManager.updateCache(caseConfig);
		} catch (Exception e) {
			logger.error("error", e);
			throw new RuntimeException(e);
		}
	}
}
